package com.asggo.g21.handler;

import cn.dev33.satoken.exception.NotLoginException;
import com.asggo.g21.domain.R;
import com.asggo.g21.enums.ResultCode;
import com.google.common.collect.ImmutableMap;
import java.util.List;
import java.util.Optional;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

/**
 * Created by IntelliJ IDEA.
 *
 * @author eric 2024/3/27 10:40
 */
@RestControllerAdvice
@Slf4j
public class RestExceptionHandler {

  @ExceptionHandler(Exception.class)
  @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
  public R<String> exception(Exception e) {
    logError(e);

    return R.fail(e.getMessage());
  }

  @ExceptionHandler(HttpMessageNotReadableException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public R<String> httpMessageNotReadableException(HttpMessageNotReadableException e) {
    logError(e);

    return R.fail("Required request body is missing.");
  }

  @ExceptionHandler(MethodArgumentNotValidException.class)
  @ResponseStatus(HttpStatus.BAD_REQUEST)
  public R<ImmutableMap<String, String>> methodArgumentNotValidException(
      MethodArgumentNotValidException e) {
    List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
    ImmutableMap.Builder<String, String> builder = ImmutableMap.builder();
    for (FieldError fieldError : fieldErrors) {
      builder.put(fieldError.getField(), Optional.ofNullable(fieldError.getDefaultMessage()).orElse(
          ""
      ));
    }
    return R.fail(ResultCode.METHOD_ARGUMENT_NOT_VALID_EXCEPTION, builder.build());
  }

  @ExceptionHandler(NotLoginException.class)
  @ResponseStatus(HttpStatus.OK)
  public R<ResultCode> notLoginException(
      NotLoginException e) {
    logError(e);
    return R.fail(ResultCode.NOT_LOGIN, null);
  }

  private void logError(Exception e) {
    log.error("ex = {}", ExceptionUtils.getStackTrace(e));
  }
}
